=x= 🌵 建立 Overview Manager - Content Page 後台頁面。
📌 進到 Yachts 頁面可以看到上方的不同型號輪播圖及左側型號側邊欄,這個部分的資料我們已經在 Yacht Manager - Content Page 做完後台了,而操作 Yachts 頁面內容後可以發現,上方的輪播頁及紅框的內容區塊,都是依據左側邊欄的型號決定,而紅框的內容區塊,則會因為內部上方的小導覽列操作改變內容,另外可以仔細操作會發現小導覽列的 Video 並不是每個型號都有,所以內容區塊才會把小導覽列包含進去,今天的文章將專注在製作 Overview 頁面內的資料,分別有 :
🧠 左上區塊 - 型號下拉選單 + 尺寸附圖上傳 + PDF 上傳。
🧠 右上區塊 - 尺寸動態新增輸入欄位 + 下載標題 + Video 連結。
🧠 下半區塊 - 主要圖文編輯器。
<h6>YachYacht Model :</h6>
<asp:DropDownList ID="DListModel" runat="server" DataSourceID="SqlDataSource1" DataTextField="yachtModel" DataValueField="id" AutoPostBack="True" Width="100%" Font-Bold="True" class="btn btn-outline-primary dropdown-toggle" OnSelectedIndexChanged="DListModel_SelectedIndexChanged" ></asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TayanaYachtConnectionString %>" SelectCommand="SELECT [yachtModel], [id] FROM [Yachts]"></asp:SqlDataSource>
<hr />
<h6>Dimensions Image :</h6>
<asp:Literal ID="LiteralDimImg" runat="server"></asp:Literal>
<div class="input-group my-3">
<asp:FileUpload ID="DimImgUpload" runat="server" class="btn btn-outline-primary btn-block" />
<asp:Button ID="BtnUploadDimImg" runat="server" Text="Upload" class="btn btn-primary" OnClick="BtnUploadDimImg_Click" />
</div>
<span class="badge badge-pill badge-warning text-dark">*Upload by No Choose File Could Clean File!</span>
<hr />
<h6>Downloads File :</h6>
<asp:Literal ID="PDFpreview" runat="server" ></asp:Literal>
<div class="input-group my-3">
<asp:FileUpload ID="FileUpload" runat="server" class="btn btn-outline-primary btn-block" />
<asp:Button ID="BtnUploadFile" runat="server" Text="Upload" class="btn btn-primary" OnClick="BtnUploadFile_Click" />
</div>
<span class="badge badge-pill badge-warning text-dark">*Upload by No Choose File Could Clean File!</span>
<head>
內引用 PDF.js 用來在頁面預覽 PDF 內容<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.min.js"></script>
<h6>Dimensions Text :</h6>
<table class="table table-hover">
<thead>
<tr class="table-info">
<th>Item<asp:Button ID="AddRow" runat="server" Text="Add Row" class="btn btn-outline-primary btn-sm py-0 px-1 align-top mx-5" OnClick="AddRow_Click" /></th>
<th>Value<asp:Button ID="DeleteRow" runat="server" Text="Delete" class="btn btn-outline-danger btn-sm py-0 px-1 align-top mx-5" OnClick="DeleteRow_Click" /></th>
</tr>
</thead>
<tbody>
<asp:Literal ID="LitDimensionsHtml" runat="server"></asp:Literal>
<tr>
<th>
<p class="d-inline-block m-r-20">Dimensions Image</p>
</th>
<td>
<asp:TextBox ID="TBoxDimImg" runat="server" type="text" class="form-control" ReadOnly="True"></asp:TextBox>
</td>
</tr>
<tr>
<th>
<p class="d-inline-block m-r-20">Downloads Title</p>
</th>
<td class="table-info">
<asp:TextBox ID="TBoxDLTitle" runat="server" type="text" class="form-control"></asp:TextBox>
</td>
</tr>
<tr>
<th>
<p class="d-inline-block m-r-20">Downloads File</p>
</th>
<td>
<asp:TextBox ID="TBoxDLFile" runat="server" type="text" class="form-control" ReadOnly="True"></asp:TextBox>
</td>
</tr>
<tr>
<th>
<p class="d-inline-block m-r-20">Video URL</p>
</th>
<td class="table-info">
<asp:TextBox ID="TBoxVideo" runat="server" type="text" class="form-control" TextMode="Url"></asp:TextBox>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>
<asp:Label ID="LabUpdateTitle" runat="server" Text="Click for Update"></asp:Label>
</th>
<td>
<asp:Button ID="BtnUpdateDimensionsList" runat="server" Text="Update Dimensions List" class="btn btn-outline-primary btn-block" OnClick="BtnUpdateDimensionsList_Click" />
<asp:Label ID="LabUpdateDimensionsList" runat="server" Text="*Upload Success!" ForeColor="green" class="d-flex justify-content-center" Visible="False"></asp:Label>
</td>
</tr>
</tfoot>
</table>
<h6>Main Content :</h6>
<CKEditor:CKEditorControl ID="CKEditorControl1" runat="server" BasePath="/Scripts/ckeditor/"
Toolbar="Bold|Italic|Underline|Strike|Subscript|Superscript|-|RemoveFormat
NumberedList|BulletedList|-|Outdent|Indent|-|JustifyLeft|JustifyCenter|JustifyRight|JustifyBlock|-|BidiLtr|BidiRtl
/
Styles|Format|Font|FontSize
TextColor|BGColor
Link|Image"
Height="400px">
</CKEditor:CKEditorControl>
<asp:Label ID="LabUploadMainContent" runat="server" Visible="False" ForeColor="#009933" class="d-flex justify-content-center"></asp:Label>
<asp:Button ID="BtnUploadMainContent" runat="server" Text="Upload Overview Content" class="btn btn-outline-primary btn-block mt-3" OnClick="BtnUploadMainContent_Click" />
//宣告 List 方便用 Add 依序添加欄位資料
private List<RowData> saveRowList = new List<RowData>();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) {
ckfinderSetPath();
DListModel.DataBind(); //先綁定取得選取值
loadContent(); //取得尺寸欄位區外的主要內容
loadRowList(); //取得尺寸欄位內容
renderRowList(); //渲染尺寸欄位內容
}
}
private void ckfinderSetPath()
{
FileBrowser fileBrowser = new FileBrowser();
fileBrowser.BasePath = "/ckfinder";
fileBrowser.SetupCKEditor(CKEditorControl1);
}
//欄位表 JSON 資料
public class RowData
{
public string SaveItem { get; set; }
public string SaveValue { get; set; }
}
List<T>
為欄位 JSON 資料用。private void loadContent()
{
//清空畫面資料
TBoxVideo.Text = "";
TBoxDLTitle.Text = "";
TBoxDimImg.Text = "";
TBoxDLFile.Text = "";
PDFpreview.Text = "";
LiteralDimImg.Text = "";
//依下拉選單選取型號取出資料
string selectModel_id = DListModel.SelectedValue;
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
string sql = "SELECT * FROM Yachts WHERE id = @selectModel_id";
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read()) {
//渲染畫面
CKEditorControl1.Text = HttpUtility.HtmlDecode(reader["overviewContentHtml"].ToString());
string imgPathStr = reader["overviewDimensionsImgPath"].ToString();
string filePathStr = reader["overviewDownloadsFilePath"].ToString();
TBoxDimImg.Text = imgPathStr;
LiteralDimImg.Text = $"<img alt='Dimensions Image' class='img-thumbnail rounded mx-auto d-block' src='/Tayanahtml/upload/Images/{imgPathStr}' Width='250px'/>";
TBoxDLFile.Text = filePathStr;
PDFpreview.Text = $"<object type='application/pdf' data='/Tayanahtml/upload/files/{filePathStr}' width='250px' height='385px' class='rounded mx-auto d-block' ></object>";
}
connection.Close();
}
<object>
標籤放入畫面。private void loadRowList()
{
//依選取型號取得欄位資料更新 List<T>
string selectModel_id = DListModel.SelectedValue;
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
string sql = "SELECT * FROM Yachts WHERE id = @selectModel_id";
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.Read()) {
string loadJson = HttpUtility.HtmlDecode(reader["overviewDimensionsJSON"].ToString());
saveRowList = JsonConvert.DeserializeObject<List<RowData>>(loadJson);
}
connection.Close();
}
private void renderRowList()
{
if (saveRowList?.Count > 0) {
string addRowHtmlStr = "";
int index = 0;
//從 List<T> 載入資料
foreach (var item in saveRowList) {
if (index == 0) {
TBoxVideo.Text = item.SaveValue;
}
if (index == 1) {
TBoxDLTitle.Text = item.SaveValue;
}
if (index > 1) {
addRowHtmlStr += $"<tr class='table-info'><th><input id='item{index}' name='item{index}' type='text' class='form-control font-weight-bold' value='{item.SaveItem}' /></th><td><input id='value{index}' name='value{index}' type='text' class='form-control' value='{item.SaveValue}' /></td></tr>";
}
index++;
}
//渲染畫面
LitDimensionsHtml.Text = addRowHtmlStr;
}
}
🌵 JSON 資料前兩筆是 Video 連結及 PDF 顯示文字。
🌵 尺寸動態增刪欄位用 HTML 的 <input>
標籤並賦予 id。
protected void DListModel_SelectedIndexChanged(object sender, EventArgs e)
{
//隱藏上傳成功提示
LabUploadMainContent.Visible = false;
LabUpdateDimensionsList.Visible = false;
//渲染畫面
loadContent();
loadRowList();
renderRowList();
}
protected void BtnUploadDimImg_Click(object sender, EventArgs e)
{
string savePath = Server.MapPath("~/Tayanahtml/upload/Images/");
string fileName = DimImgUpload.FileName;
string selectModel_id = DListModel.SelectedValue;
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
//有選檔案才可上傳,沒選檔案則執行清空
if (DimImgUpload.HasFile) {
string sqlDel = "SELECT overviewDimensionsImgPath FROM Yachts WHERE id = @selectModel_id";
SqlCommand commandDel = new SqlCommand(sqlDel, connection);
commandDel.Parameters.AddWithValue("@selectModel_id", selectModel_id);
//刪除舊圖檔
connection.Open();
SqlDataReader reader = commandDel.ExecuteReader();
if (reader.Read()) {
string delFileName = reader["overviewDimensionsImgPath"].ToString();
if (!String.IsNullOrEmpty(delFileName)) {
File.Delete(savePath + delFileName);
}
}
connection.Close();
//儲存圖片檔案及圖片名稱
//檢查專案資料夾內有無同名檔案,有同名就加流水號
DirectoryInfo directoryInfo = new DirectoryInfo(savePath);
string[] fileNameArr = fileName.Split('.');
int count = 0;
foreach (var fileItem in directoryInfo.GetFiles()) {
if (fileItem.Name.Contains(fileNameArr[0])) {
count++;
}
}
fileName = fileNameArr[0] + $"({count + 1})." + fileNameArr[1];
DimImgUpload.SaveAs(savePath + fileName);
//更新資料
string sql = "UPDATE Yachts SET overviewDimensionsImgPath = @fileName WHERE id = @selectModel_id";
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@fileName", fileName);
command.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
//渲染畫面
loadContent();
loadRowList();
renderRowList();
}
else {
//沒選檔案點上傳則清空
string sql = "UPDATE Yachts SET overviewDimensionsImgPath = @imgPath WHERE id = @selectModel_id";
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@imgPath", "");
command.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
//渲染畫面
loadContent();
loadRowList();
renderRowList();
}
}
protected void BtnUploadFile_Click(object sender, EventArgs e)
{
string savePath = Server.MapPath("~/Tayanahtml/upload/files/");
string fileName = FileUpload.FileName;
string selectModel_id = DListModel.SelectedValue;
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
//有選檔案才可上傳
if (FileUpload.HasFile) {
//先刪除舊檔
string sqlDel = "SELECT overviewDownloadsFilePath FROM Yachts WHERE id = @selectModel_id";
SqlCommand commandDel = new SqlCommand(sqlDel, connection);
commandDel.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
SqlDataReader reader = commandDel.ExecuteReader();
if (reader.Read()) {
string delFileName = reader["overviewDownloadsFilePath"].ToString();
if (!String.IsNullOrEmpty(delFileName)) {
File.Delete(savePath + delFileName);
}
}
connection.Close();
//儲存上傳檔案
//檢查專案資料夾內有無同名檔案,有同名就加流水號
DirectoryInfo directoryInfo = new DirectoryInfo(savePath);
int count = 0;
foreach (var fileItem in directoryInfo.GetFiles()) {
if (fileItem.Name.Contains(fileName)) {
count++;
}
}
string[] fileNameArr = fileName.Split('.');
fileName = fileNameArr[0] + $"({count + 1})." + fileNameArr[1];
FileUpload.SaveAs(savePath + fileName);
//更新資料庫資料
string sql = "UPDATE Yachts SET overviewDownloadsFilePath = @fileName WHERE id = @selectModel_id";
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@fileName", fileName);
command.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
//渲染畫面
loadContent();
loadRowList();
renderRowList();
}
else {
//沒選檔案則清空資料
string sqlDelPath = "UPDATE Yachts SET overviewDownloadsFilePath = @fileName WHERE id = @selectModel_id";
SqlCommand commandDelPath = new SqlCommand(sqlDelPath, connection);
commandDelPath.Parameters.AddWithValue("@fileName", "");
commandDelPath.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
commandDelPath.ExecuteNonQuery();
connection.Close();
//渲染畫面
loadContent();
loadRowList();
renderRowList();
}
}
protected void AddRow_Click(object sender, EventArgs e)
{
//將 JSON 資料載入 List<T>
loadRowList();
//增加新欄位
saveRowList.Add(new RowData { SaveItem = "", SaveValue = "" });
//更新資料庫資料
uploadRowList();
//渲染畫面
renderRowList();
//將畫面移至出現上傳按鈕處
Page.SetFocus(BtnUpdateDimensionsList);
}
private void uploadRowList()
{
//先更新 List<T> 前兩個資料 Video 及 Download File
saveRowList[0].SaveValue = TBoxVideo.Text;
saveRowList[1].SaveValue = TBoxDLTitle.Text;
//更新 List<T> 資料,欄位內容用 Request.Form
for (int i = 2; i < saveRowList.Count; i++) {
saveRowList[i].SaveItem = Request.Form[$"item{i}"];
saveRowList[i].SaveValue = Request.Form[$"value{i}"];
}
//依選取型號更新資料庫資料
string selectModel_id = DListModel.SelectedValue;
//將 List<T> 資料轉為 JSON 格式字串
string saveRowListJsonStr = JsonConvert.SerializeObject(saveRowList);
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
string sql = "UPDATE Yachts SET overviewDimensionsJSON = @saveRowListJsonStr WHERE id = @selectModel_id";
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@saveRowListJsonStr", saveRowListJsonStr);
command.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
🌵 傳統 HTML 標籤的 <input>
內容。
🌵 欄位區的 3 個按鈕都要配合進行刷新資料庫內容。
protected void DeleteRow_Click(object sender, EventArgs e)
{
//將 JSON 資料載入 List<T>
loadRowList();
//更新資料庫資料
uploadRowList();
//刪除尺寸欄位最末欄
saveRowList.RemoveAt(saveRowList.Count - 1);
//更新資料庫資料
uploadRowList();
//渲染表格畫面
renderRowList();
//將畫面移至出現上傳按鈕處
Page.SetFocus(BtnUpdateDimensionsList);
}
protected void BtnUpdateDimensionsList_Click(object sender, EventArgs e)
{
//將 JSON 資料載入 List<T>
loadRowList();
//更新資料庫資料
uploadRowList();
//渲染表格畫面
renderRowList();
//渲染上傳成功提示
DateTime nowtime = DateTime.Now;
LabUpdateDimensionsList.Visible = true;
LabUpdateDimensionsList.Text = "*Upload Success! - " + nowtime.ToString("G");
}
protected void BtnUploadMainContent_Click(object sender, EventArgs e)
{
//將文字編輯器 HTML 內容轉為 HTML 字元編碼
string mainContentHtmlStr = HttpUtility.HtmlEncode(CKEditorControl1.Text);
//依下拉選單選取型號存入型號介紹主要圖文內容
string selectModel_id = DListModel.SelectedValue;
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
string sql = "UPDATE Yachts SET overviewContentHtml = @mainContentHtmlStr WHERE id = @selectModel_id";
SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@mainContentHtmlStr", mainContentHtmlStr);
command.Parameters.AddWithValue("@selectModel_id", selectModel_id);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
//渲染上傳成功提示
DateTime nowtime = DateTime.Now;
LabUploadMainContent.Visible = true;
LabUploadMainContent.Text = "*Upload Success! - " + nowtime.ToString("G");
}
📢 本日的重點在重複使用的方法抽出來使用的好處,及動態增刪欄位的作法,由於這個後台並非多人使用,因此使用連接資料庫刷新的作法,也有看到用 ViewState 或其它方式實作的方法,可以自行研究;後續文章因為實作內容較多,並且接近收尾,都會如本文盡量將完整程式碼放上來,而分層架構處理會在最後一天文章說明實作可以精修的部分。
👀 大神系列文章 ViewState 介紹參考 : 91之ASP.NET由淺入深 不負責講座